package com.kcs.dc.report.model.logic;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import com.kcs.common.framework.GenericDto;
import com.kcs.common.utils.ConnectionUtils;
import com.kcs.common.utils.Constant;
import com.kcs.common.utils.ConstantMessage;
import com.kcs.common.utils.EventFactory;
import com.kcs.common.utils.LogWriter;
import com.kcs.common.utils.PropsUtils;
import com.kcs.common.utils.commonUtils;
import com.kcs.dc.report.model.dao.settlementDAO;
import com.kcs.dc.report.model.dao.model.settleInfoModel;
import com.kcs.dc.report.view.dto.MainMenuDto;
import com.kcs.dc.report.view.dto.SettlePastDto;
import com.kcs.dc.service.bean.request.wsSettleReqBody;
import com.kcs.dc.service.bean.request.wsSettleReqHeader;
import com.kcs.dc.service.bean.request.wsSettleRequest;
import com.kcs.dc.service.bean.response.wsSettleResponseCPT;
import com.kcs.dc.service.impl.wsSettle;

public class settlepastBL {

	private settlementDAO dao = null;
	private Connection conn = null;
	
	public settlepastBL() {
		dao = new settlementDAO();
	}
	
	public GenericDto initEvent(SettlePastDto dto) throws Exception{
		
		LogWriter.debug("<=====Start init(Settlement Past) Event=====>", Constant.LOGGER_APPLICATION);
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{
			LogWriter.debug("Step 1 : Check Authorized to use page.", Constant.LOGGER_APPLICATION);
			
			if(!commonBL.checkAuthenUsePage(dto.getUserId(), conn, "config.stm")){
				
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOHAVE_AUTHEN_PAGE, null);	        	
	        	dto.setService_id("welcome");
	        	
	        	// have error
				MainMenuDto menuDto = new MainMenuDto();
				menuDto.populate(dto);
				return menuDto;	
	        	
			}else{
				dto.setChkRevs("S");
				dto.setService_id("settlepast");
				dto.populate(dto);
			}
	
		}catch(Exception e){
			LogWriter.error("Exception settlepastBL [Method : initEvent] : " + e, Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		
		
		return dto;
	}
	
	private int getInfoDeals(SettlePastDto dto, Connection conn) throws SQLException{
	
		settleInfoModel[] models = null;
		
		int sizeModels = 0;
        
		try{
			models = dao.getInfoDeals(dto.getDealSerch(), dto.getIbcSerch(), 
									  dto.getCusNameSerch(), dto.getCcySerch(), 
									  dto.getCifSerch(),
									  dto.getChkRevs(),   
									  commonUtils.convertFormatDate(dto.getValDateFrom(), commonUtils.ddmmyyyywithslash, commonUtils.yyyymmdd), 
									  commonUtils.convertFormatDate(dto.getValDateTo(), commonUtils.ddmmyyyywithslash, commonUtils.yyyymmdd), 
									  conn);
			
	        if (models != null ) { 	
	        	// On screen Grid
				String[] cifDetail = new String[models.length];
				String[] cusNameDetail = new String[models.length];
				String[] ibcCodeDetail = new String[models.length];
				String[] branchDetail = new String[models.length];
				String[] tradNameDetail = new String[models.length];
				String[] prxGroupDetail = new String[models.length];
				String[] prxNameDetail = new String[models.length];
				String[] instrumentDetail = new String[models.length];
				String[] dealNoDetail = new String[models.length];
				String[] parentNoDetail = new String[models.length];
				String[] dealDateDetail = new String[models.length];
				String[] matDateDetail = new String[models.length];
				String[] ccyDetail = new String[models.length];
				String[] buysellDetail = new String[models.length];
				String[] rateDetail = new String[models.length];
				String[] dealAmtDetail = new String[models.length];
				String[] outAmtDetail = new String[models.length];
				
	        	for (int i = 0; i < models.length; i++) {
	        		cifDetail[i] = models[i].getCif();
	        		cusNameDetail[i] = models[i].getCutName();
	        		ibcCodeDetail[i] = models[i].getIbcCode();
	        		branchDetail[i] = models[i].getBranch();
	        		tradNameDetail[i] = models[i].getMaker_name();
	        		prxGroupDetail[i] = models[i].getProxy_group_fname();
	        		prxNameDetail[i] = models[i].getProxy_fname();
	        		instrumentDetail[i] = models[i].getInstrument();
	        		dealNoDetail[i] = models[i].getDealNo();
	        		parentNoDetail[i] = models[i].getParentNo();
	        		dealDateDetail[i] = commonUtils.convertFormatDate(models[i].getDealDate(), commonUtils.yyyymmdd, commonUtils.ddmmyyyywithslash);
	        		matDateDetail[i] = commonUtils.convertFormatDate(models[i].getMatDate(), commonUtils.yyyymmdd, commonUtils.ddmmyyyywithslash);
	        		ccyDetail[i] = models[i].getCcy();
	        		buysellDetail[i] = models[i].getBuy_sell();
	        		rateDetail[i] = commonUtils.formatNumber(models[i].getExch_rate(), 8, "#",true);
	        		dealAmtDetail[i] = commonUtils.formatNumber(models[i].getDeal_amt(), 2, "0",true);
	        		outAmtDetail[i] = commonUtils.formatNumber(models[i].getOutstd_amt(), 2, "0",true);
				}
	        	
	        	// Set data to DTO 
				dto.setCifDetail(cifDetail);
				dto.setCutNameDetail(cusNameDetail);
				dto.setIbcCodeDetail(ibcCodeDetail);
				dto.setBranchDetail(branchDetail);
				dto.setTradNameDetail(tradNameDetail);
				dto.setPrxGroupDetail(prxGroupDetail);
				dto.setPrxNameDetail(prxNameDetail);
				dto.setInstrumentDetail(instrumentDetail);
				dto.setDealNoDetail(dealNoDetail);
				dto.setParentNoDetail(parentNoDetail);
				dto.setDealDateDetail(dealDateDetail);
				dto.setMatDateDetail(matDateDetail);
				dto.setCcyDetail(ccyDetail);
				dto.setBuysellDetail(buysellDetail);
				dto.setRateDetail(rateDetail);
				dto.setDealAmtDetail(dealAmtDetail);
				dto.setOutstdAmtDetail(outAmtDetail);
				
				sizeModels = models.length;
	        }else{
	        	//clear grid.
	        	clearInfoOnGrid(dto);        	
	        }
	        
		}catch(SQLException e){
			LogWriter.error("settlepastBL [Method : getInfoDeals] : " + e, Constant.LOGGER_APPLICATION);
			throw new SQLException();
		}
		
		return sizeModels;
	}	

	private void clearInfoOnGrid(SettlePastDto dto){
		dto.setCifDetail(new String[] {});
		dto.setIbcCodeDetail(new String[] {});
		dto.setBranchDetail(new String[] {});
		dto.setTradNameDetail(new String[] {});
		dto.setPrxGroupDetail(new String[] {});
		dto.setPrxNameDetail(new String[] {});
		dto.setInstrumentDetail(new String[] {});
		dto.setDealNoDetail(new String[] {});
		dto.setCutNameDetail(new String[] {});
		dto.setParentNoDetail(new String[] {});
		dto.setDealDateDetail(new String[] {});
		dto.setMatDateDetail(new String[] {});
		dto.setCcyDetail(new String[] {});
		dto.setBuysellDetail(new String[] {});
		dto.setRateDetail(new String[] {});
		dto.setDealAmtDetail(new String[] {});
		dto.setOutstdAmtDetail(new String[] {});
	}

	public GenericDto searchEvent(SettlePastDto dto) throws Exception{
		LogWriter.debug("<=====Start search(Settlement Past) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{			
			LogWriter.debug("Step 1 : Validate dateFrom and dateTo", Constant.LOGGER_APPLICATION);
			if(!validateDateCondition(dto)){
				LogWriter.debug("Step 2 : Get information for deal by condition", Constant.LOGGER_APPLICATION);
				int sizeInfo = getInfoDeals(dto, conn);
				
				LogWriter.debug("Length of Information for Settle-Past : " + sizeInfo, Constant.LOGGER_APPLICATION);
				if (sizeInfo == 0){
					// Don't have data.
					dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOT_FOUND, null);
					if(!dto.getIbcSerch().equals("")) dto.setIbcSerch_Attr(Constant.ERR_ATTR);
					if(!dto.getCusNameSerch().equals("")) dto.setCusNameSerch_Attr(Constant.ERR_ATTR);
					if(!dto.getCcySerch().equals("")) dto.setCcySerch_Attr(Constant.ERR_ATTR);
					if(!dto.getCifSerch().equals("")) dto.setCifSerch_Attr(Constant.ERR_ATTR);
					if(!dto.getDealSerch().equals("")) dto.setDealSerch_Attr(Constant.ERR_ATTR);
						
				}		
			}else{
				clearInfoOnGrid(dto);
			}
			
			dto.setService_id("settlepast");
			
		}catch(Exception e){
			LogWriter.error("Exception settlepastBL [Method : searchEvent] : " + e, Constant.LOGGER_APPLICATION);
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
	
		return dto;	
	}
	
	private boolean validateDateCondition(SettlePastDto dto){
		boolean isError = false;
		

		if (dto.getValDateFrom().equals("") || dto.getValDateTo().equals("")){   //Both not input.
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INPUT_VALDATE, null);
			dto.setFocus_Attr("valDateFrom");
			dto.setValDateFrom_Attr(Constant.ERR_ATTR);
			dto.setValDateTo_Attr(Constant.ERR_ATTR);
			
			isError = true;		
		}else if(dto.getValDateFrom().equals("") && !dto.getValDateTo().equals("")){  //From not input but To input.
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INPUT_VALDATE, null);
			dto.setValDateFrom_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateFrom");
			
			isError = true;
		}else if(!commonUtils.isValidDateFormat(dto.getValDateFrom())){  //From invalid format.
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMATE_DATE, null);
			dto.setValDateFrom_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateFrom");
			
			if(!commonUtils.isValidDateFormat(dto.getValDateTo())){  //To invalid format.
				dto.setValDateTo_Attr(Constant.ERR_ATTR);
			}
			
			isError = true;
		}else if(!commonUtils.isValidDateFormat(dto.getValDateTo())){  //To invalid format.
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMATE_DATE, null);
			dto.setValDateTo_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateTo");
			
			isError = true;
		}else if(commonUtils.convert_ddmmyyyy2int(dto.getValDateFrom()) >= 
				commonUtils.convert_ddmmyyyy2int(commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.ddmmyyyywithslash))){
			// From more than system date
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_DATE_LESSTHAN_SYSDATE, null);
			dto.setValDateFrom_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateFrom");
			
			isError = true;
		}else if(commonUtils.convert_ddmmyyyy2int(dto.getValDateTo()) >= 
				commonUtils.convert_ddmmyyyy2int(commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.ddmmyyyywithslash))){
			// To more than system date
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_DATE_LESSTHAN_SYSDATE, null);
			dto.setValDateTo_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateTo");
			
			isError = true;
		}else if(commonUtils.convert_ddmmyyyy2int(dto.getValDateTo()) < commonUtils.convert_ddmmyyyy2int(dto.getValDateFrom())){
			dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_DATETO_LESSTHAN, null);
			dto.setValDateTo_Attr(Constant.ERR_ATTR);					
			dto.setFocus_Attr("valDateTo");
			
			isError = true;
		}
		
		return isError;
	}
	
	public GenericDto editEvent(SettlePastDto dto) throws Exception{
		// Redirect settle_past_detail.jsp
		LogWriter.info("<=====Start edit(Settlement Past) Event=====>", Constant.LOGGER_APPLICATION);
		
		int rowIndex = Integer.parseInt(dto.getRowIndex());
		
		dto.setTxt_cif(dto.getCifDetail()[rowIndex]);
		dto.setTxt_buysell(dto.getBuysellDetail()[rowIndex]);
		dto.setTxt_cutName(dto.getCutNameDetail()[rowIndex]);
		dto.setTxt_ccy(dto.getCcyDetail()[rowIndex]);
		dto.setTxt_dealNo(dto.getDealNoDetail()[rowIndex]);
		dto.setTxt_dealAmt(dto.getDealAmtDetail()[rowIndex]);
		dto.setTxt_parentNo(dto.getParentNoDetail()[rowIndex]);
		dto.setTxt_outstdAmt(dto.getOutstdAmtDetail()[rowIndex]);
		dto.setTxt_dealDate(dto.getDealDateDetail()[rowIndex]);
		dto.setTxt_ibcCode(dto.getIbcCodeDetail()[rowIndex]);
		dto.setTxt_matDate(dto.getMatDateDetail()[rowIndex]);
		dto.setSettFlag("");
		dto.setChkRevs(dto.getChkRevs());
		
		// detail string array is '1' for default show on screen.
		String[] settleAmtDetail = new String[1];
		String[] refDetail = new String[1];
		String[] commentDetail = new String[1];
		String[] errDetail = new String[1];
		String[] errCode = new String[1];
		
		settleAmtDetail[0] = "";
		refDetail[0] = "";
		commentDetail[0] = "";
		errDetail[0] = "";
		errCode[0] = "";
		
		dto.setSettAmtDetail(settleAmtDetail);
		dto.setRefNoDetail(refDetail);
		dto.setCommentDetail(commentDetail);
		dto.setErrDetail(errDetail);
		dto.setErrCode(errCode);
		
		dto.setService_id("settlepastdetail");
		
		return dto;				
	}
	
	public GenericDto backEvent(SettlePastDto dto) throws Exception{
		
		LogWriter.info("<=====Start back(Settlement Past) Event=====>", Constant.LOGGER_APPLICATION);
		
		try{
			LogWriter.info("Step 1 : Initial back go to Settlement Past Page.", Constant.LOGGER_APPLICATION);
			
			EventFactory event = new EventFactory();
			dto = (SettlePastDto) event.executeBL("settlepast", "search", dto);
			
			return dto;
	
		}catch(Exception e){
			LogWriter.error("Exception settlepastBL [Method : backEvent] : " + e.getMessage(), Constant.LOGGER_APPLICATION);			
		}
		
		return dto;
	}

	public GenericDto saveEvent(SettlePastDto dto) throws Exception{
		LogWriter.info("<=====Start save(Settlement Past) Event=====>", Constant.LOGGER_APPLICATION);
		
		wsSettleReqHeader hd = null;
		wsSettleReqBody[] bdArr = null;
    	wsSettleReqBody bd = null;
    	ArrayList<wsSettleReqBody> arr = new ArrayList<wsSettleReqBody>();
    	
    	conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
    	
    	try{
			LogWriter.debug("Step 1 : Set Header WSSettleOnline.", Constant.LOGGER_APPLICATION);
			hd = new wsSettleReqHeader();
	    	hd.setNumOfReqRec(dto.getRefNoDetail().length);
	    	hd.setSystem("DCTP");
	    	hd.setServiceID("WS0002O");
	    	String genReqId = "DCT"
	    				+ commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmddhhmmss)
	    				+ dto.getUserId().substring(dto.getUserId().length()-3);
	    	hd.setRequestID(genReqId);
	    	LogWriter.debug("@system:'DCTP', @serviceID='WS00020', @requestID='"+genReqId+"', @num_rec="+dto.getRefNoDetail().length, Constant.LOGGER_APPLICATION);	    	
	    	// ======================================================================== //
	    	
	    	// Prepare variable for kerp error.
	    	boolean haveError = false;
	    	String[] errDetail = new String[dto.getRefNoDetail().length];
	    	String[] errCode = new String[dto.getRefNoDetail().length];

	    	// ======================================================================= //
	    
	    	LogWriter.debug("Step 2 : Loop set Body WSSettleOnline.", Constant.LOGGER_APPLICATION);
			for (int i = 0; i < dto.getRefNoDetail().length; i++) {
				errDetail[i] = "";
		    	errCode[i] = "";
				
		    	bd = new wsSettleReqBody();
		    	bd.setDealId(dto.getTxt_dealNo());
		    	
		    	// check refNo, setAmt must to specific.
		    	String errMsg = basicCheckBody(dto, dto.getRefNoDetail()[i], dto.getSettAmtDetail()[i], dto.getSettFlag()); 
		    	if(!errMsg.equals("")){
		    		
		    		errDetail[i] = errMsg;
					errCode[i] = Constant.ERR_ATTR;
					
					haveError = true;
		    	}else{
		    		bd.setCcyAmt(commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[i]).doubleValue());
		    	}		    	
		    	bd.setSettleFlag(dto.getSettFlag());
		    	bd.setSourceRef(dto.getRefNoDetail()[i]);   	
		    	arr.add(bd);
		    	
		    	LogWriter.debug("@rowIndex='" + (i+1) + "', " +
		    				    "@dealID='"+dto.getTxt_dealNo()+"', " +
		    				    "@settleAmt='"+dto.getSettAmtDetail()[i]+"', " +
		    				    "@settleFlag='"+dto.getSettFlag()+"', " +
		    				    "@refNo='" + dto.getRefNoDetail()[i] +"'", Constant.LOGGER_APPLICATION);		    	
			}			
		    bdArr = (wsSettleReqBody[]) arr.toArray(new wsSettleReqBody[arr.size()]);
			// ======================================================================== //
		    
		    // Case have error before call web-service then show error screen.
		    if(haveError){
		    	dto.setErrDetail(errDetail);
				dto.setErrCode(errCode);
				/*Include error : Sett/Revs. Flag*/
				dto.setSettFlag_Attr(Constant.ERR_ATTR);
				
				dto.setService_id("settlepastdetail");
				
				return dto;
		    }
		   // ======================================================================== //
		    
		    // Call WSSettleOnline.
		    wsSettleRequest req = new wsSettleRequest(hd,bdArr);		    	
		    wsSettle settle = new wsSettle();
		    wsSettleResponseCPT res = settle.wsSettle(req);
		    
		    LogWriter.debug("Step 3 : Return response WSSettleOnline.", Constant.LOGGER_APPLICATION);
		    LogWriter.debug("==>Header Response", Constant.LOGGER_APPLICATION);
		    LogWriter.debug("@System : " + res.getHeader().getSystem() + ", " +
			    			"@ServiceID : " + res.getHeader().getServiceID() + ", " +
			    			"@RequestID : " + res.getHeader().getRequestID() + ", " +
			    			"@resp_code : " + res.getHeader().getRespCode() + ", " +
			    			"@resp_desc : " + res.getHeader().getRespDesc() + ", " +
			    			"@respTime : " + res.getHeader().getRespTime(), Constant.LOGGER_APPLICATION);
		       
		    if (res.getHeader().getRespCode().equals("0")){
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.INF_SETTLE_SUCCESS, null);
		    	
		    	LogWriter.debug("Step 4 : Update comment", Constant.LOGGER_APPLICATION);
		    	for (int i = 0; i < dto.getRefNoDetail().length; i++) {
					if (dao.updateCommentAndByUserOnDealMovement(
							conn,
							dto.getTxt_dealNo(),
							commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmdd),
							(dto.getSettFlag().equals("S"))?
									commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[i]).doubleValue()*(-1)
								   :commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[i]).doubleValue()*(1),
							genReqId, dto.getRefNoDetail()[i],
							dto.getCommentDetail()[i], dto.getUserId())) {
						LogWriter.debug(" Update comment success.", Constant.LOGGER_APPLICATION);
					}
				}
		    	
		    	LogWriter.debug("Step 5: Call Search function", Constant.LOGGER_APPLICATION);				
				EventFactory event = new EventFactory();
				dto = (SettlePastDto) event.executeBL("settlepast", "search", dto);
				
				dto.setService_id("settlepast");
		    	
		    }else{		    	
		    	setErrormsgFromWS(dto);
		    	
		    	LogWriter.debug("==>Body Response(Have Error)", Constant.LOGGER_APPLICATION);		    	

				for (int i = 0; i < res.getBody().length; i++) {
					if (res.getBody()[i].getErrStatus().equals("Y")){
						errDetail[i] = res.getBody()[i].getErrDesc();  
						errCode[i] = Constant.ERR_ATTR;
						
					}
			    	LogWriter.debug("@DealId : " + res.getBody()[i].getDealId() + ", " +
			    					"@Source : " + res.getBody()[i].getSourceRef() + ", " +
			    					"@ErrStatus : " + res.getBody()[i].getErrStatus() + ", " +
			    					"@ErrDesc : " + res.getBody()[i].getErrDesc(), Constant.LOGGER_APPLICATION);						
				}	
				
				dto.setErrDetail(errDetail);
				dto.setErrCode(errCode);
				
				dto.setService_id("settlepastdetail");
		    }
								
    	}catch(Exception e){
    		LogWriter.error("Exception settlepastBL [Method : saveEvent] : " + e.initCause(e), Constant.LOGGER_APPLICATION);
    	}finally{
			ConnectionUtils.closeConnection(conn);
		}
	
		return dto;
				
	}
	
	private String basicCheckBody(SettlePastDto dto, String refNo, String settAmt, String settleFlag) {

   	 	 // Check Body input.    		   		
		if(refNo.equals("") || settAmt.equals("") || settleFlag.equals("")){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_REPORT, ConstantMessage.ERR_REF_SETAMT_REQ);
		}else if(!commonUtils.isNumeric(String.valueOf(settAmt))){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMAT_NUM);
		}else if(commonUtils.convertStrtoBigDecimal(settAmt).doubleValue() < 0){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC);
	   	} 		
   	 
	   	 return "";
   }

	private void setErrormsgFromWS(SettlePastDto dto){
		dto.setErrArr(Constant.ERR_ATTR);
    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_SETTLE_FAIL, null);
	}
}
